#ifndef MEMORY_MANAGER_H
#define MEMORY_MANAGER_H

#include "../../include/gudb.h"
#include <stdint.h>
#include <stdbool.h>
#include <pthread.h>

// Memory pool configuration
#define MEM_POOL_MIN_SIZE    (4 * 1024)      // 4KB minimum allocation
#define MEM_POOL_MAX_SIZE    (64 * 1024 * 1024)  // 64MB maximum pool
#define MEM_POOL_ALIGNMENT   8               // 8-byte alignment
#define MEM_POOL_MAX_POOLS   16              // Maximum number of pools

// Buffer pool configuration  
#define BUFFER_POOL_MAX_PAGES    (GUDB_PAGE_CACHE_SIZE / GUDB_PAGE_SIZE)
#define BUFFER_POOL_HASH_SIZE    1024
#define BUFFER_POOL_MAX_DIRTY    256         // Maximum dirty pages before flush

// Memory allocation types
typedef enum {
    MEM_TYPE_PAGE_BUFFER,
    MEM_TYPE_WAL_BUFFER,
    MEM_TYPE_QUERY_BUFFER,
    MEM_TYPE_INDEX_BUFFER,
    MEM_TYPE_TEMP_BUFFER,
    MEM_TYPE_COUNT
} mem_type_t;

// Memory block structure
typedef struct mem_block {
    void* ptr;
    size_t size;
    mem_type_t type;
    bool in_use;
    struct mem_block* next;
    struct mem_block* prev;
} mem_block_t;

// Memory pool structure
typedef struct mem_pool {
    char name[32];
    size_t total_size;
    size_t used_size;
    size_t peak_usage;
    uint32_t alloc_count;
    uint32_t free_count;
    mem_block_t* free_list;
    mem_block_t* used_list;
    pthread_mutex_t mutex;
} mem_pool_t;

// Buffer page entry
typedef struct buffer_page {
    uint32_t page_id;
    gudb_page* page_data;
    bool dirty;
    bool pinned;
    uint32_t pin_count;
    uint64_t last_access_time;
    uint64_t access_count;
    
    // Hash chain
    struct buffer_page* hash_next;
    struct buffer_page* hash_prev;
    
    // LRU chain
    struct buffer_page* lru_next;
    struct buffer_page* lru_prev;
} buffer_page_t;

// Buffer pool structure
typedef struct buffer_pool {
    buffer_page_t* pages;
    buffer_page_t** hash_table;
    buffer_page_t* lru_head;
    buffer_page_t* lru_tail;
    
    uint32_t total_pages;
    uint32_t used_pages;
    uint32_t dirty_pages;
    uint32_t pinned_pages;
    
    // Statistics
    uint64_t cache_hits;
    uint64_t cache_misses;
    uint64_t reads;
    uint64_t writes;
    uint64_t evictions;
    
    pthread_mutex_t mutex;
    pthread_cond_t flush_cond;
} buffer_pool_t;

// Memory manager structure
typedef struct memory_manager {
    mem_pool_t pools[MEM_POOL_MAX_POOLS];
    buffer_pool_t* buffer_pool;
    
    // Global statistics
    size_t total_allocated;
    size_t peak_usage;
    uint64_t alloc_requests;
    uint64_t free_requests;
    uint64_t oom_failures;  // Out of memory failures
    
    // Background flush thread
    pthread_t flush_thread;
    bool flush_thread_running;
    
    pthread_mutex_t global_mutex;
} memory_manager_t;

// Memory manager API
memory_manager_t* mm_init(size_t total_memory);
int mm_cleanup(memory_manager_t* mm);

// Memory allocation API
void* mm_alloc(memory_manager_t* mm, size_t size, mem_type_t type);
void mm_free(memory_manager_t* mm, void* ptr);
void* mm_realloc(memory_manager_t* mm, void* ptr, size_t new_size);
void* mm_aligned_alloc(memory_manager_t* mm, size_t size, size_t alignment, mem_type_t type);

// Buffer pool API
int bp_init(buffer_pool_t* bp, uint32_t num_pages);
int bp_cleanup(buffer_pool_t* bp);
buffer_page_t* bp_get_page(buffer_pool_t* bp, uint32_t page_id);
int bp_put_page(buffer_pool_t* bp, buffer_page_t* page);
int bp_pin_page(buffer_pool_t* bp, buffer_page_t* page);
int bp_unpin_page(buffer_pool_t* bp, buffer_page_t* page);
int bp_mark_dirty(buffer_pool_t* bp, buffer_page_t* page);
int bp_flush_page(buffer_pool_t* bp, buffer_page_t* page);
int bp_flush_all_dirty(buffer_pool_t* bp);

// LRU management
int lru_promote(buffer_pool_t* bp, buffer_page_t* page);
buffer_page_t* lru_evict_candidate(buffer_pool_t* bp);
int lru_insert_head(buffer_pool_t* bp, buffer_page_t* page);
int lru_remove(buffer_pool_t* bp, buffer_page_t* page);

// Hash table management
uint32_t hash_page_id(uint32_t page_id);
buffer_page_t* hash_lookup(buffer_pool_t* bp, uint32_t page_id);
int hash_insert(buffer_pool_t* bp, buffer_page_t* page);
int hash_remove(buffer_pool_t* bp, buffer_page_t* page);

// Memory pool management
int pool_init(mem_pool_t* pool, const char* name, size_t size);
int pool_cleanup(mem_pool_t* pool);
void* pool_alloc(mem_pool_t* pool, size_t size);
void pool_free(mem_pool_t* pool, void* ptr);
size_t pool_available(const mem_pool_t* pool);

// Background operations
void* flush_thread_func(void* arg);
int schedule_flush(memory_manager_t* mm);

// Statistics and monitoring
void mm_print_stats(const memory_manager_t* mm);
void bp_print_stats(const buffer_pool_t* bp);
size_t mm_get_usage(const memory_manager_t* mm, mem_type_t type);
double bp_get_hit_ratio(const buffer_pool_t* bp);

// Memory defragmentation
int mm_defragment(memory_manager_t* mm);
int pool_compact(mem_pool_t* pool);

// Memory pressure handling
int mm_handle_pressure(memory_manager_t* mm);
int mm_free_unused(memory_manager_t* mm);

#endif // MEMORY_MANAGER_H